package com.xu.cloud.codegenerator.util;

import cn.hutool.core.util.StrUtil;
import com.xu.cloud.codegenerator.pojo.dto.ColumnDTO;
import com.xu.cloud.codegenerator.pojo.dto.TableDTO;
import com.xu.cloud.common.util.JsonUtil;
import com.xu.cloud.common.util.LocalDateTimeUtil;
import com.xu.cloud.common.util.VelocityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.zip.ZipOutputStream;

/**
 * @author xuguan
 * @since 2024/1/21
 */
@Slf4j
public class GeneratorUtil {
    /**
     * 生成代码
     */
    public static void generatorCode(TableDTO tableDTO, ZipOutputStream zos) {
        // 配置信息
        final Properties config = getConfigProperties();
        boolean hasBigDecimal = false;
        boolean hasList = false;
        // 表名转换成Java类名
        String[] tablePrefixes = {};
        if (Objects.nonNull(config.getProperty("tablePrefix"))) {
            tablePrefixes = config.getProperty("tablePrefix").split(",");
        }
        String className = tableToJava(tableDTO.getTableName(), tablePrefixes);
        tableDTO.setClassName(StringUtils.capitalize(className));
        tableDTO.setUnCapitalClassName(StringUtils.uncapitalize(className));

        // 列信息
        final List<ColumnDTO> columnDTOList = tableDTO.getColumnDTOList();
        for (ColumnDTO columnDTO : columnDTOList) {
            // 列名转换成Java属性名
            final String propertyName = columnToJava(columnDTO.getColumnName());
            columnDTO.setCapitalPropertyName(StringUtils.capitalize(propertyName));
            columnDTO.setPropertyName(propertyName);

            // 列的数据类型，转换成Java类型
            String propertyType = config.getProperty(columnDTO.getDataType(), columnToJava(columnDTO.getDataType()));
            columnDTO.setPropertyType(propertyType);

            if (!hasBigDecimal && propertyType.equals("BigDecimal")) {
                hasBigDecimal = true;
            }
            if (!hasList && "array".equals(columnDTO.getExtra())) {
                hasList = true;
            }
            // 是否主键
            if ("PRI".equalsIgnoreCase(columnDTO.getColumnKey())) {
                tableDTO.setPk(columnDTO);
            }
        }

        log.info("{}表和字段信息: {}", tableDTO.getTableName(), JsonUtil.toJsonString(tableDTO));

        // 设置velocity资源加载器
        VelocityUtil.initVelocity();

        String mainPath = config.getProperty("mainPath", "com.xu");

        // 封装模板数据
        Map<String, Object> map = new HashMap<>();
        map.put("tableName", tableDTO.getTableName());
        map.put("comments", tableDTO.getTableComment());
        map.put("pk", tableDTO.getPk());
        map.put("className", tableDTO.getClassName());
        map.put("unCapitalClassName", tableDTO.getUnCapitalClassName());
        map.put("pathName", tableDTO.getClassName().toLowerCase());
        map.put("columns", tableDTO.getColumnDTOList());
        map.put("hasBigDecimal", hasBigDecimal);
        map.put("hasList", hasList);
        map.put("mainPath", mainPath);
        map.put("package", config.getProperty("package"));
        map.put("moduleName", config.getProperty("moduleName"));
        map.put("author", config.getProperty("author"));
        map.put("email", config.getProperty("email"));
        map.put("date", LocalDateTimeUtil.fmtCurrentNormDate());

        // 获取模板列表
        List<String> templates = getTemplates();
        try {
            for (String template : templates) {
                // 渲染模板
                final String renderTemplateStr = VelocityUtil.renderTemplate(template, map);
                System.out.println(renderTemplateStr);
                // // 添加到zip
                // final String fileName = getFileName(template, tableDTO.getClassName(), config.getProperty("package"), config.getProperty("moduleName"));
                // if (StringUtils.hasText(fileName)) {
                //     zos.putNextEntry(new ZipEntry(fileName));
                // }
                // StreamUtils.copy(renderTemplateStr, StandardCharsets.UTF_8, zos);
                //
                // zos.flush();
                // zos.closeEntry();
            }

        }
        // catch (IOException e) {
        //     throw GeneratorErrorCodeEnum.ERR_GENERATE_CODE.info().catchException(e);
        // }
        finally {

        }
    }

    public static List<String> getTemplates() {
        List<String> templates = new ArrayList<>();
        // templates.add("template/Controller.java.vm");
        // templates.add("template/Service.java.vm");
        // templates.add("template/ServiceImpl.java.vm");
        templates.add("template/DO.java.vm" );
        templates.add("template/Mapper.java.vm");
        templates.add("template/Mapper.xml.vm");
        //
        // templates.add("template/menu.sql.vm");
        //
        // templates.add("template/index.vue.vm");
        // templates.add("template/add-or-update.vue.vm");

        return templates;
    }

    /**
     * 表名转换成Java类名
     */
    public static String tableToJava(String tableName, String[] tablePrefixArray) {
        if (null != tablePrefixArray && tablePrefixArray.length > 0) {
            for (String tablePrefix : tablePrefixArray) {
                if (tableName.startsWith(tablePrefix)) {
                    tableName = tableName.replaceFirst(tablePrefix, "");
                }
            }
        }
        return columnToJava(tableName);
    }

    /**
     * 获取配置信息
     */
    public static Properties getConfigProperties() {
        try {
            return PropertiesLoaderUtils.loadProperties(new ClassPathResource("generator.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取文件名
     */
    public static String getFileName(String template, String className, String packageName, String moduleName) {
        String packagePath = "src" + File.separator +"main" + File.separator + "java" + File.separator;
        String resourcesPath = "src" + File.separator +"main" + File.separator + "resources" + File.separator;
        String viewPath = "src" + File.separator + "views" + File.separator + "modules" + File.separator + moduleName + File.separator;

        if (StringUtils.hasText(packageName)) {
            packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
        }

        if (template.contains("Controller.java.vm")) {
            return packagePath + "controller" + File.separator + className + "Controller.java";
        }

        if (template.contains("ServiceImpl.java.vm")) {
            return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
        }

        if (template.contains("Service.java.vm")) {
            return packagePath + "service" + File.separator + className + "Service.java";
        }

        if (template.contains("DO.java.vm")) {
            return packagePath + "pojo" + File.separator + "domain" + File.separator + className + "DO.java";
        }

        if (template.contains("Mapper.java.vm")) {
            return packagePath + "pojo" + File.separator + "mapper" + File.separator + className + "Mapper.java";
        }

        if (template.contains("Mapper.xml.vm")) {
            return resourcesPath + "mapper" + File.separator + moduleName + File.separator + className + "Mapper.xml";
        }

        if (template.contains("menu.sql.vm")) {
            return className.toLowerCase() + "_menu.sql";
        }

        if (template.contains("index.vue.vm")) {
            return viewPath + className.toLowerCase() + ".vue";
        }

        if (template.contains("add-or-update.vue.vm")) {
            return viewPath + className.toLowerCase() + "-add-or-update.vue";
        }

        return null;
    }

    /**
     * 列名转换成Java属性名
     */
    public static String columnToJava(String columnName) {
        return StrUtil.toCamelCase(columnName);
    }
}
